import numpy
import time

def loadDataSet():
    dataMat = []
    labelMat = []
    fr = open('./testSet.txt')
    for line in fr.readlines():
        oneData = line.strip().split()
        dataMat.append([1.0, float(oneData[0]), float(oneData[1])])     # ？？？第一列中的1是什么作用？？？
        labelMat.append(int(oneData[2]))
    return dataMat, labelMat


def sigmoid(inX):                   # inX is a (m*1) matrix
    # 每一个元素都是一条数据（数据点的X,Y）与weight相乘求和的结果。
    # 利用sigmoid计算是归到0，还是归到1 ？
    # 返回一个m*1的矩阵，为该inX输入情况下，0,1的判断
    return 1.0/(1+numpy.exp(-inX))


def gradAscent(dataMatIn, classLabels):
    dataMatrix = numpy.mat(dataMatIn)
    classMatrix = numpy.mat(classLabels).transpose()
    m, n = numpy.shape(dataMatrix)      # m = 100, means the row count, n = 3, means the column count
    print("log:", m, n)
    alpha = 0.001
    maxCycle = 500
    weights = numpy.ones((n, 1))                    # n行1列
    tempWeight = numpy.ones((maxCycle,n, 1))        # 存每一轮求解的weight值, 300组n行1列
    print("log:", weights)
    for k in range(maxCycle):
        h = sigmoid(dataMatrix * weights)       # 将每个数据点的值与weight矩阵相乘，得到（m*1）的矩阵，传递给sigmoid函数
        error = (classMatrix - h)                  # 返回的计算出来的0,1的分类，与原有的label相减，得到差值。（m*1）的矩阵
        weights = weights + alpha * dataMatrix.transpose() * error  # 梯度在哪里？？？
        tempWeight[k] = weights
    return weights, tempWeight

def plotBestFit(dataMat, labelMat, weights):
    import matplotlib.pyplot as plt
    #dataArr = numpy.array(dataMat)
    n = len(dataMat)             # n = 100
    xcord0 = []; ycord0 = []
    xcord1 = []; ycord1 = []
    for i in range(n):
        if int(labelMat[i]) == 0:     # class 0
            xcord0.append(dataMat[i][1])
            ycord0.append(dataMat[i][2])
        else:       # class 1
            xcord1.append(dataMat[i][1])
            ycord1.append(dataMat[i][2])
    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax.scatter(xcord0, ycord0, s=30, c='red', marker='s')
    ax.scatter(xcord1, ycord1, s=30, c='green')
    x = numpy.arange(-3.0, 3.0, 0.1)
    y = numpy.asarray((-weights[0]-weights[1]*x)/weights[2])
    y = y[0,:]
    # 给sigmoid函数的输入为0时，为两种种类的分界线
    # 所以设z = f(x, y) = w1*x + w2*y + w0 = 0，解出x，y两个自变量之间的关系
    ax.plot(x, y)
    plt.xlabel('X1')
    plt.ylabel('X2')
    plt.show()


def plotBestFitSlowly(dataMat, labelMat, weightSet):
    import matplotlib.pyplot as plt
    #dataArr = numpy.array(dataMat)
    n = len(dataMat)             # n = 100
    xcord0 = []; ycord0 = []
    xcord1 = []; ycord1 = []
    for i in range(n):
        if int(labelMat[i]) == 0:     # class 0
            xcord0.append(dataMat[i][1])
            ycord0.append(dataMat[i][2])
        else:       # class 1
            xcord1.append(dataMat[i][1])
            ycord1.append(dataMat[i][2])
    fig = plt.figure()
    ax = fig.add_subplot(1,1,1)
    ax.scatter(xcord0, ycord0, s=30, c='red', marker='s')
    ax.scatter(xcord1, ycord1, s=30, c='green')
    x = numpy.arange(-3.0, 3.0, 0.1)
    ySet = numpy.zeros((len(weightSet), len(x)))
    for id, weights in enumerate(weightSet):
        ySet[id] = numpy.asarray((-weights[0]-weights[1]*x)/weights[2])
    # 动态画出线性回归的线
    plt.axis([-5, 5, -5, 15])
    plt.xlabel('X1')
    plt.ylabel('X2')
    for id, y in enumerate(ySet):
        line = ax.plot(x, ySet[id])
        plt.show()
        time.sleep(0.1)

        # line.pop(0)


if __name__ == '__main__':
    dataMat, labelMat = loadDataSet()
    w, tempw = gradAscent(dataMat, labelMat)
    print("log:w=", w)
    #plotBestFit(dataMat, labelMat, w)
    plotBestFitSlowly(dataMat, labelMat, tempw)